/*
 * (c) 2012 Leonid Bensman, lbensman.cs00@gtalumni.org
 */
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace CalcSig.Serializers
{
    public class AudioHashSerializerCSV : HashSerializer<AudioHash>, IDisposable
    {
        internal const string CSVHeader = @"FileName,AudioHash,FileHash,FileSize";
        private readonly StreamWriter outStream;

        public AudioHashSerializerCSV(IHashCalculator hashCalculator)
            : this(hashCalculator, "Report.csv")
        {
        }

        public AudioHashSerializerCSV(IHashCalculator hashCalculator, string reportFile)
            :this(hashCalculator, File.CreateText(reportFile))
        {
        }
        
        public AudioHashSerializerCSV(IHashCalculator hashCalculator, StreamWriter outStream)
            : base(hashCalculator)
        {
            this.outStream = outStream;
            
            outStream.WriteLine(CSVHeader);
        }

        protected override void OnItemCalculated(AudioHash itemHash)
        {
            if (disposed)
            {
                throw new ObjectDisposedException(this.GetType().ToString());
            }

            lock (outStream)
            {
                outStream.WriteLine(string.Format("\"{0}\", {1}, {2}, {3}", itemHash.Path, HashAsString(itemHash.AudioStreamHash), HashAsString(itemHash.FileHash), itemHash.FileSize));
                //report.Flush();
            }
        }

        #region IDisposable Members

        // Track whether Dispose has been called.
        private bool disposed = false;

        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue 
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the 
        // runtime from inside the finalizer and you should not reference 
        // other objects. Only unmanaged resources can be disposed.
        private void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                // If disposing equals true, dispose all managed 
                // and unmanaged resources.
                if (disposing)
                {
                    // Dispose managed resources.
                    outStream.Flush();
                    outStream.Close();
                    outStream.Dispose();
                }

                // Call the appropriate methods to clean up 
                // unmanaged resources here.
                // If disposing is false, 
                // only the following code is executed.
            }
            disposed = true;
        }

        // Use C# destructor syntax for finalization code.
        // This destructor will run only if the Dispose method 
        // does not get called.
        // It gives your base class the opportunity to finalize.
        // Do not provide destructors in types derived from this class.
        ~AudioHashSerializerCSV()      
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.
            Dispose(false);
        }

        #endregion
    }
}
